package idao.engine.executor;

import idao.Query;
import idao.ResultSetHandler;
import idao.Reusable;
import idao.engine.DaoUtils;

import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Base class for all query statement executor.
 * 
 * @author huhao
 */
public class QueryExecutor extends SqlExecutor
{

    private ResultSetHandler resultSetHandler;
    private Query.ResultSetHandler resultSetHandlerMetadata;

    protected QueryExecutor(Method m)
    {
        Query query = m.getAnnotation(Query.class);
        this.parseSqlAndParameters(query.value());
        // using user specified ResultSetHandler
        resultSetHandlerMetadata = m.getAnnotation(Query.ResultSetHandler.class);
        if (resultSetHandlerMetadata != null) {
            if (resultSetHandlerMetadata.value().isAnnotationPresent(Reusable.class)) {
                resultSetHandler = this.getResultSetHandler();
            }
        } else {
            resultSetHandler = new DefaultResultSetHandler(m);
        }
    }

    @Override
    protected Object doExecute(PreparedStatement ps) throws SQLException
    {
        ResultSet rs = ps.executeQuery();
        try {
            return this.getResultSetHandler().handleResultSet(rs);
        } finally {
            DaoUtils.close(rs);
        }
    }

    private ResultSetHandler getResultSetHandler()
    {
        return resultSetHandler != null ? resultSetHandler : DaoUtils
                        .newInstance(resultSetHandlerMetadata.value(), resultSetHandlerMetadata
                                        .initParameters());
    }
}
